﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Data.Realm;

namespace Atlantyda
{
    public class TreeRoads
    {
        private System.Drawing.Point destination;
        private Dictionary<String, System.Drawing.Point> coordinates = new Dictionary<String, System.Drawing.Point>();
        private TreeNode root;
        private TreeNode finish_node;

        public TreeRoads(System.Drawing.Point destination)
        {
            this.destination = destination;
            this.root = new TreeNode();
        }

        public void genarateCoordinates()
        {
            if (destination.X >= 0)
            {
                for (int i = 0; i <= destination.X; i++)
                    for (int j = 0; j <= destination.Y; j++)
                        if (i != 0 || j != 0)
                            coordinates.Add(i + "_" + j, new System.Drawing.Point(i, j));
            }
            else
            {
                for (int i = 0; i >= destination.X; i--)
                    for (int j = 0; j <= destination.Y; j++)
                        if (i != 0 || j != 0)
                            coordinates.Add(i + "_" + j, new System.Drawing.Point(i, j));
            }
        }

        public void genarateTree()
        {
            TreeNode parent = root;
            System.Drawing.Point coordinate;
            TreeNode finish_node = null;
            while (true)
            {
                int x;
                if (destination.X < 0)
                    x = parent.Coordinate.X - 1;
                else
                    x = parent.Coordinate.X + 1;
                int y = parent.Coordinate.Y + 1;
                String key_x = x + "_" + parent.Coordinate.Y;
                String key_y = parent.Coordinate.X + "_" + y;
                if (coordinates.TryGetValue(key_x, out coordinate) && parent.LeftNode == null)
                {
                    TreeNode node = new TreeNode(coordinate, Agent.GetOrientateField(coordinate.X, coordinate.Y));
                    if (parent.Coordinate == new System.Drawing.Point(0, 0))
                        node.RotateCount = 1;
                    else if (parent.Coordinate.X == parent.Parent.Coordinate.X)
                        node.RotateCount = parent.RotateCount + 1;
                    else
                        node.RotateCount = parent.RotateCount;
                    if (parent.GoodWay == false || node.Field == null || node.Field.obstacle)
                        node.GoodWay = false;
                    else
                        node.GoodWay = true;
                    node.Parent = parent;
                    parent.LeftNode = node;
                    parent = node;
                    if (node.Coordinate == destination && node.GoodWay)
                    {
                        if (finish_node == null || finish_node.RotateCount > node.RotateCount)
                            finish_node = node;
                    }
                }
                else if (coordinates.TryGetValue(key_y, out coordinate) && parent.RightNode == null)
                {
                    TreeNode node = new TreeNode(coordinate, Agent.GetOrientateField(coordinate.X, coordinate.Y));
                    if (parent.Coordinate == new System.Drawing.Point(0, 0))
                        node.RotateCount = 0;
                    else if (parent.Coordinate.Y == parent.Parent.Coordinate.Y)
                        node.RotateCount = parent.RotateCount + 1;
                    else
                        node.RotateCount = parent.RotateCount;
                    if (parent.GoodWay == false || node.Field == null || node.Field.obstacle)
                        node.GoodWay = false;
                    else
                        node.GoodWay = true;
                    node.Parent = parent;
                    parent.RightNode = node;
                    parent = node;
                    if (node.Coordinate == destination && node.GoodWay)
                    {
                        if (finish_node == null || finish_node.RotateCount > node.RotateCount)
                            finish_node = node;
                    }
                }
                else if (parent.Parent != null)
                {
                    parent = parent.Parent;
                }
                else
                {
                    break;
                }
            }
            if (finish_node == null)
            {
                if (Agent.BadAutomatRecharge > 0)
                {
                    Random rand = new Random();
                    int num = rand.Next(0, 2);
                    if (num == 0)
                        Agent.RotateLeft();
                    else if (num == 1)
                        Agent.RotateRight();
                    else
                    {
                        Agent.RotateRight();
                        Agent.RotateRight();
                    }
                    Agent.BadAutomatRecharge = 0;
                }
                else if (destination.X < 0)
                {
                    Agent.RotateLeft();
                    Agent.BadAutomatRecharge++;
                }
                else
                {
                    Agent.RotateRight();
                    Agent.BadAutomatRecharge++;
                }
            }
            this.finish_node = finish_node;
        }

        public bool GoToEnergy()
        {
            if (finish_node != null)
            {
                List<System.Drawing.Point> steps = new List<System.Drawing.Point>();
                TreeNode node = this.finish_node;
                do
                {
                    steps.Add(node.Coordinate);
                    node = node.Parent;
                } while (node != null);
                int orientate = 1;
                for (int i = steps.Count - 1; i > 0; i--)
                {
                    if (steps[i].X == steps[i - 1].X && steps[i].Y != steps[i - 1].Y)
                    {
                        if (orientate == 1)
                            Agent.StepForward();
                        else if (orientate == 2)
                        {
                            Agent.RotateLeft();
                            Agent.StepForward();
                            orientate = 1;
                        }
                        else if (orientate == 4)
                        {
                            Agent.RotateRight();
                            Agent.StepForward();
                            orientate = 1;
                        }
                        else
                            return false;
                    }
                    else if (steps[i].X > steps[i - 1].X && steps[i].Y == steps[i - 1].Y)
                    {
                        if (orientate == 1)
                        {
                            Agent.RotateLeft();
                            Agent.StepForward();
                            orientate = 4;
                        }
                        else if (orientate == 4)
                            Agent.StepForward();
                        else
                            return false;
                    }
                    else if (steps[i].X < steps[i - 1].X && steps[i].Y == steps[i - 1].Y)
                    {
                        if (orientate == 1)
                        {
                            Agent.RotateRight();
                            Agent.StepForward();
                            orientate = 2;
                        }
                        else if (orientate == 2)
                            Agent.StepForward();
                        else
                            return false;
                    }
                }
                return true;
            }
            else
                return false;
        }

    }
}
